package org.jeecg.modules.rental.controller;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.jeecg.boot.starter.lock.client.RedissonLockClient;
import org.jeecg.boot.starter.rabbitmq.client.RabbitMqClient;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.aspect.annotation.PermissionData;
import org.jeecg.common.base.BaseMap;
import org.jeecg.common.config.TenantContext;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.rental.vo.LoginRentalAccount;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.*;
import org.jeecg.modules.message.constant.MessageConstant;
import org.jeecg.modules.rental.entity.RentalAccount;
import org.jeecg.modules.rental.entity.RentalConfig;
import org.jeecg.modules.rental.enums.RentalConfigEnums;
import org.jeecg.modules.rental.req.*;
import org.jeecg.modules.rental.service.IRentalAccountService;
import org.jeecg.modules.rental.service.IRentalConfigService;
import org.jeecg.modules.rental.util.AppMenuUtil;
import org.jeecg.modules.rental.util.EncryptedDataUtil;
import org.jeecg.modules.rental.util.RandomUtil;
import org.jeecg.modules.rental.util.WxAuthorizationUtil;
import org.jeecg.modules.rental.vo.WxSessionVO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartRequest;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.Arrays;
import java.util.List;

/**
 * @Description: 租车支付账号
 * @Author: sean
 * @Date: 2024-04-28
 * @Version: V1.0
 */
@Api(tags = "租车支付账号")
@RestController
@RequestMapping("/rental/account")
@RequiredArgsConstructor
@Slf4j
public class RentalAccountController extends JeecgController<RentalAccount, IRentalAccountService> {

    private final IRentalAccountService rentalPayAccountService;
    private final RedisUtil redisUtil;

    private final IRentalConfigService rentalConfigService;

    private final WxAuthorizationUtil wxAuthorizationUtil;

    private final AppMenuUtil appMenuUtil;

    private final RabbitMqClient rabbitMqClient;

    @Value(value="${jeecg.uploadType}")
    private String uploadType;

    @Value(value = "${jeecg.path.upload}")
    private String uploadpath;



    /**
     * 分页列表查询
     *
     * @param rentalPayAccount
     * @param pageNo
     * @param pageSize
     * @param req
     * @return
     */
    //@AutoLog(value = "租车支付账号-分页列表查询")
    @ApiOperation(value = "租车支付账号-分页列表查询", notes = "租车支付账号-分页列表查询")
    @GetMapping(value = "/list")
    @PermissionData(pageComponent="rental/account/list")
    public Result<IPage<RentalAccount>> queryPageList(RentalAccount rentalPayAccount,
                                                         @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                                         @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                                         HttpServletRequest req) {
        QueryWrapper<RentalAccount> queryWrapper = QueryGenerator.initQueryWrapper(rentalPayAccount, req.getParameterMap());
        Page<RentalAccount> page = new Page<RentalAccount>(pageNo, pageSize);
        IPage<RentalAccount> pageList = rentalPayAccountService.page(page, queryWrapper);
        // 遍历用户列表，对身份证号码进行脱敏处理
        for (RentalAccount record : pageList.getRecords()) {
            String identityNumber = record.getIdentityNumber();
            if (identityNumber != null && identityNumber.length() >= 14) {
                record.setIdentityNumber(identityNumber.substring(0, 6) + "********" + identityNumber.substring(14));
            }
            String phone = record.getPhone();
            if (phone != null && phone.length() >= 7) {
                String maskedPhone = phone.substring(0, 3) + "****" + phone.substring(7);
                record.setPhone(maskedPhone); // 设置脱敏后的手机号
            } else {
                record.setPhone(phone); // 手机号为空或长度不足 7 位，直接设置
            }
        }
        return Result.OK(pageList);
    }

    /**
     * 添加
     *
     * @param rentalPayAccount
     * @return
     */
    @AutoLog(value = "租车支付账号-添加")
    @ApiOperation(value = "租车支付账号-添加", notes = "租车支付账号-添加")
    @PostMapping(value = "/add")
    public Result<String> add(@RequestBody RentalAccount rentalPayAccount) {
        rentalPayAccountService.addAccount(rentalPayAccount);
        return Result.OK("common.add.success");
    }

    /**
     * 编辑
     *
     * @param rentalPayAccount
     * @return
     */
    @AutoLog(value = "租车支付账号-编辑")
    @ApiOperation(value = "租车支付账号-编辑", notes = "租车支付账号-编辑")
    @RequestMapping(value = "/edit", method = {RequestMethod.PUT, RequestMethod.POST})
    public Result<String> edit(@RequestBody RentalAccount rentalPayAccount) {
        RentalAccount payAccount = rentalPayAccountService
                .getById(rentalPayAccount.getId());
        if(ObjectUtil.isNotEmpty(rentalPayAccount.getPhone())
                && rentalPayAccount.getPhone().indexOf("**") != -1 ){
            if(StrUtil.isNotBlank(payAccount.getPhone())){
                rentalPayAccount.setPhone(null);
            }else{
                throw new JeecgBootException("手机号不应该包含*");
            }
        }
        if(ObjectUtil.isNotEmpty(rentalPayAccount.getIdentityNumber())
                && rentalPayAccount.getIdentityNumber().indexOf("**") != -1 ){
            if(StrUtil.isNotBlank(payAccount.getIdentityNumber())){
                rentalPayAccount.setIdentityNumber(null);
            }else{
                throw new JeecgBootException("身份证号不应该包含*");
            }
        }
        rentalPayAccountService.updateById(rentalPayAccount);
        return Result.OK("common.edit.success");
    }

    /**
     * 通过id删除
     *
     * @param id
     * @return
     */
    @AutoLog(value = "租车支付账号-通过id删除")
    @ApiOperation(value = "租车支付账号-通过id删除", notes = "租车支付账号-通过id删除")
    @DeleteMapping(value = "/delete")
    public Result<String> delete(@RequestParam(name = "id", required = true) String id) {
        rentalPayAccountService.removeById(id);
        return Result.OK("common.delete.success");
    }

    /**
     * 批量删除
     *
     * @param ids
     * @return
     */
    @AutoLog(value = "租车支付账号-批量删除")
    @ApiOperation(value = "租车支付账号-批量删除", notes = "租车支付账号-批量删除")
    @DeleteMapping(value = "/deleteBatch")
    public Result<String> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
        this.rentalPayAccountService.removeByIds(Arrays.asList(ids.split(",")));
        return Result.OK("common.delete.batch.success");
    }

    /**
     * 重置密码
     * @param id
     * @return
     */
    @ApiOperation(value = "租车支付账号-重置密码", notes = "租车支付账号-重置密码")
    @GetMapping(value = "/reset-password")
    public Result<RentalAccount> resetPassword(@RequestParam(name = "id", required = true) String id) {
        RentalAccount rentalPayAccount = rentalPayAccountService.initPassword(id);
        if (rentalPayAccount == null) {
            return Result.error("common.query.not.found", null);
        }
        return Result.OK(rentalPayAccount);
    }

    /**
     * 通过id查询
     *
     * @param id
     * @return
     */
    //@AutoLog(value = "租车支付账号-通过id查询")
    @ApiOperation(value = "租车支付账号-通过id查询", notes = "租车支付账号-通过id查询")
    @GetMapping(value = "/queryById")
    public Result<RentalAccount> queryById(@RequestParam(name = "id", required = true) String id) {
        RentalAccount rentalPayAccount = rentalPayAccountService.getById(id);
        if (rentalPayAccount == null) {
            return Result.error("common.query.not.found", null);
        }
        return Result.OK(rentalPayAccount);
    }

    /*实名认证*/
//    @PostMapping("/authentication")
//    @ApiOperation("身份实名认证")
//    public Result<Integer> authentication(@Valid @RequestBody AddAuthenticationReq req) throws ClientException, IOException {
//        boolean flag1 = redissonLockClient.tryLock("AUTHENTICATION" + req.getAccountId(), 0, 3);
//        if (!flag1) {
//            throw new JeecgBootException("common.too.frequent");
//        }
//        return Result.OK(rentalPayAccountService.authentication(req));
//    }


    @ApiOperation(value = "套餐退订(申请)", notes = "套餐退订(申请)")
    @GetMapping(value = "/unsubscribe/package")
    public Result<Boolean> unsubscribePackage(@ApiParam(value = "openId", name = "openId") @RequestParam(value = "openId", required = true) String openId,
                                              @ApiParam(value = "id", name = "用户套餐主键ID") @RequestParam(value = "id", required = true) String id) {
        return rentalPayAccountService.unsubscribePackage(openId, id);
    }


//    @ApiOperation(value = "发起押金退款审核", notes = "发起押金退款审核")
//    @GetMapping(value = "/deposit/refund")
//    public Result<Boolean> depositRefund(@ApiParam(value = "accountPackageId", name = "accountPackageId") @RequestParam(value = "accountPackageId", required = true) String accountPackageId) {
//        boolean flag1 = redissonLockClient.tryLock("DEPOSIT" + accountPackageId, 0, 3);
//        if (!flag1) {
//            throw new JeecgBootException("common.too.frequent");
//        }
//        return rentalPayAccountService.depositRefund(accountPackageId);
//    }

//    @ApiOperation(value = "发起退款", notes = "发起退款")
//    @GetMapping(value = "/allRefund")
//    public Result<Boolean> allRefund(@ApiParam(value = "accountPackageId", name = "accountPackageId") @RequestParam(value = "accountPackageId", required = true) String accountPackageId) {
//        boolean flag1 = redissonLockClient.tryLock("ALLREFUND" + accountPackageId, 0, 3);
//        if (!flag1) {
//            throw new JeecgBootException("common.too.frequent");
//        }
//        return rentalPayAccountService.depositRefund(accountPackageId);
//    }

//    @ApiOperation(value = "提现记录列表", notes = "提现记录列表")
//    @GetMapping(value = "/withdrawal/list")
//    public Result<Page<RentalWithdrawalReviewReq>> withdrawalList(@ApiParam(value = "openId", name = "openId") @RequestParam(value = "openId", required = true) String openId, @RequestParam(name = "pageNo", required = false) Integer pageNo, @RequestParam(name = "pageSize", required = false) int pageSize) {
//        return rentalPayAccountService.withdrawalList(openId, pageNo, pageSize);
//    }


    /**
     * 导出excel
     *
     * @param request
     * @param rentalPayAccount
     */
    @RequestMapping(value = "/exportXls")
    public ModelAndView exportXls(HttpServletRequest request, RentalAccount rentalPayAccount) {
        return super.exportXls(request, rentalPayAccount, RentalAccount.class, "租车支付账号");
    }

    /**
     * 通过excel导入数据
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
    public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
        return super.importExcel(request, response, RentalAccount.class);
    }


//    @ApiOperation(value = "获取用户套餐列表", notes = "获取用户套餐列表")
//    @GetMapping(value = "/packge/list")
//    public Result<List<AccountRentalPackegeRsp>> accountPackge(@ApiParam(value = "openId", name = "openId") @RequestParam(value = "openId", required = true) String openId,
//                                                               @ApiParam(value = "accountPackgeType", name = "用户套餐状态（1：过期，2：使用中，3：退订）") @RequestParam(value = "accountPackgeType", required = false) Integer accountPackgeType
//    ) {
//        return rentalPayAccountService.accountPackge(openId, accountPackgeType);
//    }

//    @ApiOperation(value = "获取可购买套餐列表", notes = "获取可购买套餐列表")
//    @GetMapping(value = "/allow/coupon/list")
//    public Result<List<RentalPackge>> allowCoupons(@ApiParam(value = "openId", name = "openId") @RequestParam(value = "openId", required = true) String openId) {
//        return rentalPayAccountService.allowCoupons(openId);
//    }


//    @ApiOperation(value = "获取套餐列表", notes = "获取套餐列表")
//    @GetMapping(value = "/package/list")
//    public Result<List<RentalPackge>> packageList(@ApiParam(value = "carTypeId", name = "电池类型id") @RequestParam(value = "carTypeId", required = true) String carTypeId) {
//        return rentalPayAccountService.packageList(carTypeId);
//    }

//    @ApiOperation(value = "获取电池类型押金列表", notes = "获取电池类型押金列表")
//    @PostMapping(value = "/deposit/list")
//    public Result<List<RentalCarType>> list() {
//        return Result.OK(rentalPayAccountService.lists());
//    }

    /**
     * 获取session_key 和 oppenId
     * @param code
     * @param appId
     * @return
     */
    @GetMapping("/app/auth/{appId}/{code}")
    @ApiOperation("授权")
    public Result auth(
            @ApiParam(required = true, name = "appId", value = "小程序id") @PathVariable(value = "appId") String appId,
            @ApiParam(required = true, name = "code", value = "待授权串") @PathVariable(value = "code") String code) {
        Result<JSONObject> result = new Result<JSONObject>();
        WxSessionVO wxSession = wxAuthorizationUtil.code2session(appId, code);
        LoginRentalAccount rentalAccount = rentalPayAccountService.getLoginRentalAccountByWxOpenId(wxSession.getOpenid());
        // 生成token
        String token = JwtUtil.sign(rentalAccount.getAccountCode(), rentalAccount.getSysOrgCode(), rentalAccount.getPassword());
        // 设置token缓存有效时间
        redisUtil.set(CommonConstant.PREFIX_RENTAL_ACCOUNT_TOKEN + token, token);
        long expire =  JwtUtil.EXPIRE_TIME * 12 * 7 / 1000  ;
        redisUtil.expire(CommonConstant.PREFIX_RENTAL_ACCOUNT_TOKEN + token, expire);
        JSONObject obj = new JSONObject();
        obj.put("token", token);
        obj.put("info", rentalAccount);
        obj.put("wxSession", wxSession);
        //TODO 优化客户端菜单
        List<String> menuList = appMenuUtil.appClientMenus(appId);
        obj.put("menuList", menuList);
        List<RentalConfig> rentalConfigList = rentalConfigService.list();
        obj.put("configList", rentalConfigList);
        result.setResult(obj);
        result.success("登录成功");
        return result;
    }

    @GetMapping("/app/analysis-phone")
    @ApiOperation("权限获取用户手机号")
    public Result analysisPhone(
            @ApiParam(name = "appId", value = "小程序id") @RequestParam(value = "appId") String appId,
            @ApiParam(value = "数据源", name = "data") @RequestParam(value = "data") String data,
            @ApiParam(value = "小程序code", name = "code") @RequestParam(value = "code") String code,
            @ApiParam(value = "解密向量", name = "iv") @RequestParam(value = "iv") String iv) {
        WxSessionVO wxSession = wxAuthorizationUtil.code2session(appId, code);
        return Result.OK(EncryptedDataUtil.getPhone(data, wxSession.getSessionKey(), iv));
    }

    @PostMapping("/app/bind-phone")
    @ApiOperation("新增")
    public Result bindPhone(@ApiParam(value = "手机号码", name = "phone") @RequestParam(value = "phone") String phone) throws Exception {
        rentalPayAccountService.bindPhone(phone);
        return Result.OK();
    }


//    @GetMapping("/app/authPhone")
//    @ApiOperation("权限获取用户手机号")
//    public Result authPhone(@ApiParam(value = "数据源", name = "data") @RequestParam(value = "data", required = true) String data,
//                            @ApiParam(value = "临时会话", name = "session_key") @RequestParam(value = "session_key", required = true) String session_key,
//                            @ApiParam(value = "解密向量", name = "iv") @RequestParam(value = "iv", required = true) String iv) {
//        return Result.OK(EncryptedDataUtil.getPhone(data, session_key, iv));
//    }


    @GetMapping("/app/query/authentication")
    @ApiOperation("身份实名认证状态查询")
    public Result<RentalAccount> queryAuthentication() {
        RentalAccount payAccountInfoRsp = rentalPayAccountService.queryAuthentication();
        return Result.OK(payAccountInfoRsp);
    }


    @ApiOperation("登录接口")
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public Result<JSONObject> login(@RequestBody AccountLoginReq loginReq, @RequestParam(value="client", required=false, defaultValue="APP" ) String client) {
        Result<JSONObject> result = new Result<JSONObject>();
        String account = loginReq.getAccount();
        String password = loginReq.getPassword();
//        String captcha = loginReq.getCaptcha();
//        if (captcha == null) {
//            result.error500("验证码无效");
//            return result;
//        }
//        String lowerCaseCaptcha = captcha.toLowerCase();
//        String realKey = Md5Util.md5Encode(lowerCaseCaptcha + loginReq.getCheckKey(), "utf-8");
//        Object checkCode = redisUtil.get(realKey);
//        //当进入登录页时，有一定几率出现验证码错误 #1714
//        if (checkCode == null || !checkCode.toString().equals(lowerCaseCaptcha)) {
//            log.warn("验证码错误，key= {} , Ui checkCode= {}, Redis checkCode = {}", loginReq.getCheckKey(), lowerCaseCaptcha, checkCode);
//            result.error500("验证码错误");
//            return result;
//        }
        //update-end-author:taoyan date:20190828 for:校验验证码

        //1. 校验用户是否有效
        //update-begin-author:wangshuai date:20200601 for: 登录代码验证用户是否注销bug，if条件永远为false
//        LambdaQueryWrapper<RentalAccount> queryWrapper = new LambdaQueryWrapper<>();
//        queryWrapper.and(wrapper -> {
//            wrapper.eq(RentalAccount::getPhone, account).or().eq(RentalAccount::getEmail, account);
//        });
        LoginRentalAccount rentalAccount = rentalPayAccountService.getLoginRentalAccountByAccount(account);
        if(ObjectUtil.isEmpty(rentalAccount)){
            result.error500("rentalpayaccount.incorrect.username.or.password");
            return result;
        }
        //update-end-author:wangshuai date:20200601 for: 登录代码验证用户是否注销bug，if条件永远为false
//        result = sysUserService.checkUserIsEffective(sysUser);
//        if (!result.isSuccess()) {
//            return result;
//        }
        //2. 校验用户名或密码是否正确
        String userpassword = PasswordUtil.encrypt(rentalAccount.getAccountCode(), password, rentalAccount.getSalt());
        String syspassword = rentalAccount.getPassword();
        if (!syspassword.equals(userpassword)) {
            result.error500("rentalpayaccount.incorrect.username.or.password");
            return result;
        }

        // update-end--Author:sunjianlei Date:20210802 for：获取用户租户信息
        // 生成token
        String token = JwtUtil.sign(rentalAccount.getAccountCode(), rentalAccount.getSysOrgCode(), syspassword);
        // 设置token缓存有效时间
        redisUtil.set(CommonConstant.PREFIX_RENTAL_ACCOUNT_TOKEN + token, token);
        long expire = JwtUtil.EXPIRE_TIME * 2 / 1000;
        if(StrUtil.isNotBlank(client) && "APP".equals(client)){
            expire =  JwtUtil.EXPIRE_TIME * 12 * 7 / 1000  ;
        }
        redisUtil.expire(CommonConstant.PREFIX_RENTAL_ACCOUNT_TOKEN + token, expire);
        //update-begin--Author:liusq  Date:20210126  for：登录成功，删除redis中的验证码
//        redisUtil.del(realKey);
        //update-begin--Author:liusq  Date:20210126  for：登录成功，删除redis中的验证码
//        baseCommonService.addLog("用户名: " + username + ",登录成功！", CommonConstant.LOG_TYPE_1, null, loginUser);
        //update-end--Author:wangshuai  Date:20200714  for：登录日志没有记录人员
        //绑定cid
        rentalPayAccountService.bindCid(rentalAccount.getId(), loginReq.getCid(), loginReq.getClientCode(), loginReq.getClientPlatform());
        JSONObject obj = new JSONObject();
        obj.put("token", token);
        RentalConfig rentalConfig = rentalConfigService.get(RentalConfigEnums.STATIC_DOMAIN_URL.getConfigKey());
        rentalAccount.setImage(rentalConfig.getConfigValue() + rentalAccount.getImage());
        obj.put("accountInfo", rentalAccount);
        result.setResult(obj);
        result.success("rentalpayaccount.login.succeeded");
        return result;
    }

    /**
     * 通过账户名
     * @param code
     * @return
     */
    @ApiOperation(value = "租车支付账号-通过id查询", notes = "租车支付账号-通过id查询")
    @GetMapping(value = "/getAccountByCode")
    public RentalAccount getAccountByPhone(@RequestParam(name = "code", required = true) String code) {
        RentalAccount rentalAccount = rentalPayAccountService.getAccountByCode(code);
        return rentalAccount;
    }


    @PostMapping("/change-passwd")
    @ApiOperation("重置密码")
    public Result changePasswd(@Valid @RequestBody ResetPasswdReq resetPasswdReq) {
        String originalPassword = resetPasswdReq.getOriginal_password();
        String newPassword = resetPasswdReq.getPassword();

        if(originalPassword.equals(newPassword)){
            return Result.error("rentalpayaccount.password.not.same");
        }

        //用户当前用户信息
        LoginRentalAccount rentalAccount = (LoginRentalAccount) SecurityUtils.getSubject().getPrincipal();
        //查询数据库里的记录
        RentalAccount existingAccount = rentalPayAccountService.getById(rentalAccount.getId());
        //比较原密码是否正确
        String userpassword = PasswordUtil.encrypt(existingAccount.getAccountCode(), originalPassword, existingAccount.getSalt());
        String syspassword = existingAccount.getPassword();
        if (!syspassword.equals(userpassword)) {
            return Result.error("rentalpayaccount.original.password.incorrect");
        }

        String encryptNewPassword = PasswordUtil.encrypt(existingAccount.getAccountCode(), newPassword, existingAccount.getSalt());
        existingAccount.setPassword(encryptNewPassword);
        rentalPayAccountService.updateById(existingAccount);
        return Result.OK("rentalpayaccount.password.reset.successful");
    }

    @PostMapping("/register")
    @ApiOperation("注册用户")
    public Result<JSONObject> register(@Valid @RequestBody RegisterReq registerReq) {
        Result<JSONObject> result = new Result<>();

        String phone = registerReq.getPhone();
        String captcha = registerReq.getCaptcha().toLowerCase();
        String checkKey = registerReq.getCheckKey();
        String password = registerReq.getPassword();

        // 校验验证码
        String realKey = Md5Util.md5Encode(captcha + checkKey, "utf-8");
        Object checkCode = redisUtil.get(realKey);
        if (checkCode == null || !checkCode.toString().equals(captcha)) {
            log.warn("验证码错误，key= {} , Ui checkCode= {}, Redis checkCode = {}", checkKey, captcha, checkCode);
            result.error500("rentalpayaccount.verification.code.error");
            return result;
        }

        // 检查手机号是否已注册
        LambdaQueryWrapper<RentalAccount> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RentalAccount::getPhone, phone);
        RentalAccount existingAccount = rentalPayAccountService.getOne(queryWrapper);
        if (existingAccount != null) {
            result.error500("rentalpayaccount.phone.already.registered");
            return result;
        }

        // 创建新用户
        RentalAccount newAccount = new RentalAccount();
        newAccount.setPhone(phone);
        newAccount.setAccountCode(RandomUtil.getRandomCode());
        String salt = oConvertUtils.randomGen(8);
        newAccount.setSalt(salt);
        String passwordEncode = PasswordUtil.encrypt(newAccount.getAccountCode(), password, salt);
        newAccount.setPassword(passwordEncode);
        rentalPayAccountService.save(newAccount);

        // 登录成功，删除 Redis 中的验证码
        redisUtil.del(realKey);
        return result.success("rentalpayaccount.register.succeeded");
    }

    @PostMapping("/send_register_code")
    @ApiOperation("发送注册验证码")
    public Result<JSONObject> sendVerifyCode(@Valid @RequestBody SendVerifyCodeReq sendVerifyCode) {
        Result<JSONObject> result = new Result<>();

        String email = sendVerifyCode.getEmail();

        //检测上一次的验证码是否过期
        String realKey = Md5Util.md5Encode(email, "utf-8");
        Object checkCode = redisUtil.get(realKey);
        if (ObjectUtil.isNotEmpty(checkCode)) {
            log.warn("验证码未失效不要重复发送");
            JSONObject json = new JSONObject();
            json.put("expire", redisUtil.getExpire(realKey));
            result.setCode(3000);
            result.setMessage("rentalpayaccount.repeat.send.verify.code");
            result.setResult(json);
            return result;
        }

        // 检查手机号是否已注册
        LambdaQueryWrapper<RentalAccount> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RentalAccount::getEmail, email);
        RentalAccount existingAccount = rentalPayAccountService.getOne(queryWrapper);
        if (existingAccount != null) {
            result.error500("rentalpayaccount.phone.already.registered");
            return result;
        }

        //生成验证码
        final String BASE_CHECK_CODES = "qwertyuiplkjhgfdsazxcvbnmQWERTYUPLKJHGFDSAZXCVBNM1234567890";
        String code = cn.hutool.core.util.RandomUtil.randomString(BASE_CHECK_CODES,4);

        String lowerCaseCode = code.toLowerCase();

        //通过mq发送验证码
        BaseMap param = new BaseMap();
        param.put("tenantId", TenantContext.getTenant());
        param.put("to", email);
        param.put("bizType", "register_code");
        param.put("arguments", new String[]{lowerCaseCode});
        rabbitMqClient.sendMessage(MessageConstant.MESSAGE_EMAIL_QUENE_NAME, param);

        //存到redis中
        long expire = 60 * 5;
        JSONObject json = new JSONObject();
        json.put("expire", expire);
        result.success("rentalpayaccount.send.verify.code.successful");
        result.setResult(json);
        redisUtil.set(realKey, lowerCaseCode, expire);
        return result;
    }


    @PostMapping("/register-email")
    @ApiOperation("邮箱注册用户")
    public Result<JSONObject> registerEmail(@Validated @RequestBody RegisterEmailReq registerReq) {
        Result<JSONObject> result = new Result<>();

        String email = registerReq.getEmail();
        String captcha = registerReq.getCaptcha().toLowerCase();
        String password = registerReq.getPassword();

        // 校验验证码
        String realKey = Md5Util.md5Encode(email, "utf-8");
        Object checkCode = redisUtil.get(realKey);
        if (checkCode == null || !checkCode.toString().equals(captcha)) {
            log.warn("验证码错误，key= {} , Ui checkCode= {}, Redis checkCode = {}", captcha, checkCode);
            result.error500("rentalpayaccount.verification.code.error");
            return result;
        }

        // 检查手机号是否已注册
        LambdaQueryWrapper<RentalAccount> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RentalAccount::getEmail, email);
        RentalAccount existingAccount = rentalPayAccountService.getOne(queryWrapper);
        if (existingAccount != null) {
            result.error500("rentalpayaccount.email.already.registered");
            return result;
        }

        // 创建新用户
        RentalAccount newAccount = new RentalAccount();
        newAccount.setEmail(email);
        newAccount.setAccountCode(RandomUtil.getRandomCode());
        String salt = oConvertUtils.randomGen(8);
        newAccount.setSalt(salt);
        String passwordEncode = PasswordUtil.encrypt(newAccount.getAccountCode(), password, salt);
        newAccount.setPassword(passwordEncode);
        rentalPayAccountService.save(newAccount);
        // 登录成功，删除 Redis 中的验证码
        redisUtil.del(realKey);
        return result.success("rentalpayaccount.register.succeeded");
    }


    @PostMapping("/send_reset_code")
    @ApiOperation("发送重置密码验证码")
    public Result<JSONObject> sendResetCode(@Valid @RequestBody SendVerifyCodeReq sendVerifyCode) {
        Result<JSONObject> result = new Result<>();

        String email = sendVerifyCode.getEmail();

        //检测上一次的验证码是否过期
        String realKey = Md5Util.md5Encode( "RESET_CODE_" + email, "utf-8");
        Object checkCode = redisUtil.get(realKey);
        if (ObjectUtil.isNotEmpty(checkCode)) {
            log.warn("验证码未失效不要重复发送");
            JSONObject json = new JSONObject();
            json.put("expire", redisUtil.getExpire(realKey));
            result.setCode(3000);
            result.setMessage("rentalpayaccount.repeat.send.verify.code");
            result.setResult(json);
            return result;
        }

        // 检查手机号是否已注册
        LambdaQueryWrapper<RentalAccount> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RentalAccount::getEmail, email);
        RentalAccount existingAccount = rentalPayAccountService.getOne(queryWrapper);
        if (ObjectUtil.isEmpty(existingAccount) ) {
            result.error500("rentalpayaccount.email.already.unregister");
            return result;
        }

        //生成验证码
        final String BASE_CHECK_CODES = "qwertyuiplkjhgfdsazxcvbnmQWERTYUPLKJHGFDSAZXCVBNM1234567890";
        String code = cn.hutool.core.util.RandomUtil.randomString(BASE_CHECK_CODES,4);
        String lowerCaseCode = code.toLowerCase();

        //通过mq发送验证码
        BaseMap param = new BaseMap();
        param.put("tenantId", TenantContext.getTenant());
        param.put("to", email);
        param.put("bizType", "register_code");
        param.put("arguments", new String[]{lowerCaseCode});
        rabbitMqClient.sendMessage("message.email", param);

        //存到redis中
        long expire = 60 * 5;
        JSONObject json = new JSONObject();
        json.put("expire", expire);
        result.success("rentalpayaccount.send.verify.code.successful");
        result.setResult(json);
        redisUtil.set(realKey, lowerCaseCode, expire);
        return result;
    }

    /**
     * 设置重置密码的标识，无该标识客户无法修改密码
     * @param searchPwdReq
     * @return
     */
    @PostMapping("/set-reset-flag")
    @ApiOperation("找回密码")
    public Result<JSONObject> setResetFlag(@Valid @RequestBody SearchPwdReq searchPwdReq) {
        Result<JSONObject> result = new Result<>();

        String email = searchPwdReq.getEmail();
        String captcha = searchPwdReq.getCaptcha().toLowerCase();

        // 校验验证码
        String realKey = Md5Util.md5Encode("RESET_CODE_" + email, "utf-8");
        Object checkCode = redisUtil.get(realKey);
        if (checkCode == null || !checkCode.toString().equals(captcha)) {
            log.warn("验证码错误，key= {} , Ui checkCode= {}, Redis checkCode = {}", captcha, checkCode);
            result.error500("rentalpayaccount.verification.code.error");
            return result;
        }
        long expire = 60 * 5;
        String resetFlagKey = Md5Util.md5Encode("RESET_PWD_" + email, "utf-8");
        redisUtil.set(resetFlagKey, 1, expire);
        return result.success("rentalpayaccount.reset.pwd.identifier.successfully");
    }

    /**
     * 重置密码
     * @param resetPwdReq
     * @return
     */
    @PostMapping("/reset-pwd")
    @ApiOperation("找回密码")
    public Result<JSONObject> resetPwd(@Valid @RequestBody ResetPwdReq resetPwdReq) {
        Result<JSONObject> result = new Result<>();
        String password = resetPwdReq.getPassword();
        //验证是否设置了重置密码的标识
        String realKey = Md5Util.md5Encode("RESET_PWD_" + resetPwdReq.getEmail(), "utf-8");
        if(!redisUtil.hasKey(realKey)){
            return result.error500("rentalpayaccount.password.change.operation.timed.out");
        }
        RentalAccount payAccount = rentalPayAccountService
                .getOne(new QueryWrapper<RentalAccount>().eq("email", resetPwdReq.getEmail()));
        // 修改密码
        String passwordEncode = PasswordUtil.encrypt(payAccount.getAccountCode(), password, payAccount.getSalt());
        payAccount.setPassword(passwordEncode);
        rentalPayAccountService.updateById(payAccount);
        //删除设置了重置密码的标识
        redisUtil.del(realKey);
        return result.success("rentalpayaccount.password.reset.successful");
    }

    @GetMapping("/remove")
    @ApiOperation("注销用户")
    public Result remove() {
        LoginRentalAccount rentalAccount = (LoginRentalAccount) SecurityUtils.getSubject().getPrincipal();
        rentalPayAccountService.removeById(rentalAccount.getId());
        return Result.OK("rentalpayaccount.remove.succeeded");
    }



    @ApiOperation("设置昵称")
    @RequestMapping(value = "/set-account-name", method = RequestMethod.GET)
    public Result setAccountName(@RequestParam(value="accountName") String accountName) {
        LoginRentalAccount rentalAccount = (LoginRentalAccount) SecurityUtils.getSubject().getPrincipal();
        RentalAccount payAccount = rentalPayAccountService.getById(rentalAccount.getId());
        payAccount.setAccountName(accountName);
        rentalPayAccountService.updateById(payAccount);
        return Result.OK("rentalpayaccount.successfully.account.name");
    }


    @ApiOperation("设置头像")
    @RequestMapping(value = "/set-avatar", method = RequestMethod.POST)
    public Result setAvatar(MultipartRequest files) {
        StringBuffer savePath = new StringBuffer();
        files.getMultiFileMap().forEach( (name, multipartFiles)->{
            String filePath = CommonUtils.uploadnew(multipartFiles.get(0), uploadpath, "temp", uploadType);
            savePath.append(filePath);
        });
        LoginRentalAccount rentalAccount = (LoginRentalAccount) SecurityUtils.getSubject().getPrincipal();
        RentalAccount payAccount = rentalPayAccountService.getById(rentalAccount.getId());
        payAccount.setImage(savePath.toString());
        rentalPayAccountService.updateById(payAccount);
        RentalConfig rentalConfig = rentalConfigService.get(RentalConfigEnums.STATIC_DOMAIN_URL.getConfigKey());
        return Result.OK("rentalpayaccount.successfully.avatar", rentalConfig.getConfigValue() + savePath);
    }


}
